package main

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"

	"github.com/elazarl/goproxy"
)

type logger struct{}

func (l logger) Printf(format string, v ...any) {
	fmt.Printf("[log] "+format+"\n", v...)
}
func parseCA(caCert, caKey []byte) (*tls.Certificate, error) {
	parsedCert, err := tls.X509KeyPair(caCert, caKey)
	if err != nil {
		return nil, err
	}
	if parsedCert.Leaf, err = x509.ParseCertificate(parsedCert.Certificate[0]); err != nil {
		return nil, err
	}
	return &parsedCert, nil
}

func isInFilter(r *http.Request) bool {
	return strings.Contains(r.Host, "example.com") || strings.Contains(r.Host, "example1.com")
}
func main() {
	log := logger{}
	proxy := goproxy.NewProxyHttpServer()
	proxy.Verbose = true
	proxy.Logger = log

	_caCert, _ := os.ReadFile("./ca/ca.crt")
	_caKey, _ := os.ReadFile("./ca/ca.key")

	cert, err := parseCA(_caCert, _caKey)
	if err != nil {
		fmt.Println(err)
	}
	customCaMitm := &goproxy.ConnectAction{Action: goproxy.ConnectMitm, TLSConfig: goproxy.TLSConfigFromCA(cert)}
	var customAlwaysMitm goproxy.FuncHttpsHandler = func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
		return customCaMitm, host
	}
	// 用自定义证书代理https
	proxy.OnRequest().HandleConnect(customAlwaysMitm)
	// 请求过滤器
	proxy.OnRequest().DoFunc(func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
		if isInFilter(r) {
			log.Printf("[过滤]: %v %v %v %v", r.Method, r.Host, r.URL, r.Header)
		} else {
			log.Printf("Request 0: %v %v %v %v", r.Method, r.Host, r.URL, r.Header)
		}

		return r, nil
	})

	// 响应修改器
	proxy.OnResponse().DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
		// 读取响应体
		body, err := io.ReadAll(ctx.Resp.Body)
		if err != nil {
			fmt.Println(ctx.Req.Host, "读取响应体失败:", err)
		} else {
			if isInFilter(ctx.Req) {
				fmt.Println(ctx.Req.Host, "[过滤]读取响应体:", string(body))
			}
		}

		ctx.Resp.Body = io.NopCloser(bytes.NewBuffer(body))
		return r
	})

	http.ListenAndServe(":8080", proxy)
}
